"""
版本状态流转审批服务
负责管理版本状态流转的审批流程
"""
from typing import Dict, List, Optional
from datetime import datetime
from motor.motor_asyncio import AsyncIOMotorDatabase  # pyright: ignore[reportMissingImports]
from bson import ObjectId  # pyright: ignore[reportMissingImports]
import logging

from app.services.version_auto_transition_service import VersionAutoTransitionService
from app.services.version_completion_service import VersionCompletionService

logger = logging.getLogger(__name__)


class VersionApprovalService:
    """版本状态流转审批服务"""
    
    def __init__(self, db: AsyncIOMotorDatabase):
        self.db = db
        self.auto_transition_service = VersionAutoTransitionService(db)
        self.completion_service = VersionCompletionService(db)
    
    async def create_approval_request(
        self,
        version_id: ObjectId,
        from_status: str,
        to_status: str,
        reason: Optional[str],
        requester: dict,
        completion_data: Optional[Dict] = None,
        approval_flow_type: str = "simple"
    ) -> Dict:
        """
        创建审批请求
        
        Args:
            version_id: 版本ID
            from_status: 源状态
            to_status: 目标状态
            reason: 流转原因
            requester: 申请人信息
            completion_data: 完成度数据（可选）
            approval_flow_type: 审批流程类型（simple/multi/auto）
        
        Returns:
            审批请求信息
        """
        # 权限检查
        from app.services.permission_service import PermissionService, Permissions
        
        has_request_permission = PermissionService.has_permission(
            requester, Permissions.VERSION_TRANSITION_REQUEST
        )
        has_update_permission = PermissionService.has_permission(
            requester, Permissions.VERSION_UPDATE
        )
        
        if not has_request_permission and not has_update_permission:
            raise ValueError("权限不足：无法提交版本状态流转申请")
        
        # 获取版本信息
        version = await self.db.versions.find_one({"_id": version_id})
        if not version:
            raise ValueError("版本不存在")
        
        # 验证状态
        # 从状态管理系统获取默认状态
        from app.utils.state_utils import get_default_state_code
        default_status = await get_default_state_code(self.db, "version")
        current_status = version.get("status", default_status or "")
        if current_status != from_status:
            raise ValueError(f"版本当前状态为 {current_status}，与申请状态 {from_status} 不符")
        
        # 判断是否需要审批
        from app.services.version_transition_rules import VersionTransitionRules
        rule = VersionTransitionRules.get_rule(from_status, to_status)
        
        if not rule:
            raise ValueError(f"不存在从 {from_status} 到 {to_status} 的流转规则")
        
        # 如果不需要审批且是自动审批，直接执行流转
        if not rule.require_approval and approval_flow_type == "auto":
            result = await self.auto_transition_service._execute_transition(
                version_id, from_status, to_status,
                completion_data or {}, "auto_approved"
            )
            return {
                "id": None,
                "status": "auto_approved",
                "transition_result": result
            }
        
        # 检查是否需要原因
        if rule.require_reason and not reason:
            raise ValueError("该状态流转需要提供原因")
        
        # 获取完成度数据（如果未提供）
        if completion_data is None:
            # 从状态管理系统获取草稿和规划状态
            from app.utils.state_utils import get_state_code_by_name_keywords
            draft_code = await get_state_code_by_name_keywords(self.db, "version", ["草稿", "draft"])
            planning_code = await get_state_code_by_name_keywords(self.db, "version", ["规划中", "planning"])
            early_statuses = [s for s in [draft_code, planning_code] if s]
            if from_status in early_statuses:
                completion_data = await self.completion_service.calculate_readiness_metrics(
                    version_id, version
                )
            else:
                completion_data = await self.completion_service.calculate_completion_rate(version_id)
        
        # 设置审批人
        approvers = []
        if approval_flow_type == "multi":
            approvers = await self._get_approvers_for_version(version_id, version)
        else:
            approver = await self._get_primary_approver(version_id, version)
            if approver:
                approvers = [approver]
        
        if not approvers:
            raise ValueError("无法找到审批人，请检查项目配置")
        
        # 创建审批请求
        approval_request = {
            "version_id": version_id,
            "from_status": from_status,
            "to_status": to_status,
            "reason": reason,
            "completion_data": completion_data,
            "requester_id": ObjectId(requester.get("user_id")),
            "requested_at": datetime.utcnow(),
            "status": "pending",
            "approval_flow_type": approval_flow_type,
            "approvers": approvers,
            "current_approver_index": 0,
            "approval_results": [],
            "created_at": datetime.utcnow(),
            "updated_at": datetime.utcnow()
        }
        
        result = await self.db.version_transition_approvals.insert_one(approval_request)
        created_request = await self.db.version_transition_approvals.find_one(
            {"_id": result.inserted_id}
        )
        
        return {
            "id": str(created_request["_id"]),
            "status": created_request["status"],
            "approvers": created_request["approvers"]
        }
    
    async def approve_request(
        self,
        approval_request_id: ObjectId,
        approver: dict,
        approved: bool,
        notes: Optional[str] = None
    ) -> Dict:
        """
        审批请求
        
        Args:
            approval_request_id: 审批请求ID
            approver: 审批人信息
            approved: 是否批准
            notes: 审批意见
        
        Returns:
            审批结果
        """
        # 权限检查
        from app.services.permission_service import PermissionService, Permissions
        
        if not PermissionService.has_permission(approver, Permissions.VERSION_TRANSITION_APPROVE):
            raise ValueError("权限不足：无法审批版本状态流转申请")
        
        # 获取审批请求
        approval_request = await self.db.version_transition_approvals.find_one(
            {"_id": approval_request_id}
        )
        
        if not approval_request:
            raise ValueError("审批请求不存在")
        
        if approval_request["status"] != "pending":
            raise ValueError(f"审批请求状态为 {approval_request['status']}，无法审批")
        
        approver_id = ObjectId(approver.get("user_id"))
        
        # 检查是否是当前审批人
        approvers = approval_request.get("approvers", [])
        current_index = approval_request.get("current_approver_index", 0)
        
        if approval_request["approval_flow_type"] == "simple":
            # 简单审批：检查是否是指定的审批人
            if not approvers or approvers[0].get("user_id") != str(approver_id):
                raise ValueError("您不是该审批请求的审批人")
        else:
            # 多级审批：检查是否是当前级别的审批人
            if current_index >= len(approvers):
                raise ValueError("审批流程已完成")
            
            current_approver = approvers[current_index]
            if current_approver.get("user_id") != str(approver_id):
                raise ValueError("您不是当前级别的审批人")
        
        # 记录审批结果
        approval_result = {
            "approver_id": approver_id,
            "approved": approved,
            "notes": notes,
            "approved_at": datetime.utcnow()
        }
        
        approval_results = approval_request.get("approval_results", [])
        approval_results.append(approval_result)
        
        # 更新审批请求
        update_data = {
            "approval_results": approval_results,
            "updated_at": datetime.utcnow()
        }
        
        if approval_request["approval_flow_type"] == "simple":
            # 简单审批：直接完成
            if approved:
                update_data["status"] = "approved"
                update_data["approved_by"] = approver_id
                update_data["approved_at"] = datetime.utcnow()
                update_data["approval_notes"] = notes
            else:
                update_data["status"] = "rejected"
                update_data["rejection_reason"] = notes
        else:
            # 多级审批
            if approved:
                # 如果还有下一级，继续审批流程
                if current_index + 1 < len(approvers):
                    update_data["current_approver_index"] = current_index + 1
                else:
                    # 所有级别都通过，完成审批
                    update_data["status"] = "approved"
                    update_data["approved_by"] = approver_id
                    update_data["approved_at"] = datetime.utcnow()
            else:
                # 任何一级拒绝，审批失败
                update_data["status"] = "rejected"
                update_data["rejection_reason"] = notes
        
        await self.db.version_transition_approvals.update_one(
            {"_id": approval_request_id},
            {"$set": update_data}
        )
        
        # 如果审批通过，执行状态流转
        if update_data.get("status") == "approved":
            await self._execute_transition(approval_request)
        
        return {
            "id": str(approval_request_id),
            "status": update_data.get("status", "pending"),
            "approved": approved
        }
    
    async def _execute_transition(self, approval_request: Dict):
        """执行审批通过后的状态流转"""
        version_id = approval_request["version_id"]
        from_status = approval_request["from_status"]
        to_status = approval_request["to_status"]
        completion_data = approval_request.get("completion_data", {})
        
        await self.auto_transition_service._execute_transition(
            version_id, from_status, to_status,
            completion_data, "approved"
        )
        
        # 更新审批请求，记录执行结果
        await self.db.version_transition_approvals.update_one(
            {"_id": approval_request["_id"]},
            {"$set": {
                "executed_at": datetime.utcnow(),
                "updated_at": datetime.utcnow()
            }}
        )
    
    async def cancel_request(
        self,
        approval_request_id: ObjectId,
        user: dict
    ) -> Dict:
        """取消审批请求"""
        approval_request = await self.db.version_transition_approvals.find_one(
            {"_id": approval_request_id}
        )
        
        if not approval_request:
            raise ValueError("审批请求不存在")
        
        if approval_request["status"] != "pending":
            raise ValueError(f"审批请求状态为 {approval_request['status']}，无法取消")
        
        requester_id = ObjectId(approval_request["requester_id"])
        user_id = ObjectId(user.get("user_id"))
        
        # 权限检查：只能取消自己的申请，或拥有撤销权限
        from app.services.permission_service import PermissionService, Permissions
        
        is_requester = requester_id == user_id
        has_revoke_permission = PermissionService.has_permission(
            user, Permissions.VERSION_TRANSITION_REVOKE
        )
        
        if not is_requester and not has_revoke_permission:
            raise ValueError("权限不足：无法取消该审批申请")
        
        # 更新状态为已取消
        await self.db.version_transition_approvals.update_one(
            {"_id": approval_request_id},
            {"$set": {
                "status": "cancelled",
                "cancelled_at": datetime.utcnow(),
                "updated_at": datetime.utcnow()
            }}
        )
        
        return {
            "id": str(approval_request_id),
            "status": "cancelled"
        }
    
    async def get_pending_approvals(
        self,
        user: dict,
        project_id: Optional[ObjectId] = None
    ) -> List[Dict]:
        """获取待审批列表"""
        user_id = ObjectId(user.get("user_id"))
        
        # 查找需要当前用户审批的请求
        query = {
            "status": "pending",
            "$or": [
                {"approvers.user_id": str(user_id)},
                {"approvers.user_id": user_id}
            ]
        }
        
        if project_id:
            # 如果指定了项目，只查询该项目下的版本
            version_ids = await self.db.versions.find(
                {"project_id": project_id}
            ).distinct("_id")
            
            query["version_id"] = {"$in": version_ids}
        
        approvals = await self.db.version_transition_approvals.find(
            query
        ).sort("requested_at", -1).to_list(length=100)
        
        # 获取版本信息
        result = []
        for approval in approvals:
            version = await self.db.versions.find_one({"_id": approval["version_id"]})
            
            result.append({
                "id": str(approval["_id"]),
                "version_id": str(approval["version_id"]),
                "version_name": version.get("name") if version else "",
                "from_status": approval["from_status"],
                "to_status": approval["to_status"],
                "reason": approval.get("reason"),
                "requester_id": str(approval["requester_id"]),
                "requested_at": approval["requested_at"],
                "approval_flow_type": approval.get("approval_flow_type", "simple"),
                "current_approver_index": approval.get("current_approver_index", 0),
                "approvers": approval.get("approvers", [])
            })
        
        return result
    
    async def _requires_approval(
        self,
        from_status: str,
        to_status: str,
        completion_data: Optional[Dict]
    ) -> bool:
        """判断是否需要审批"""
        from app.services.version_transition_rules import VersionTransitionRules
        
        rule = VersionTransitionRules.get_rule(from_status, to_status)
        return rule and rule.require_approval
    
    async def _get_primary_approver(
        self,
        version_id: ObjectId,
        version: Dict
    ) -> Optional[Dict]:
        """获取主审批人（项目经理或项目负责人）"""
        project_id = version.get("project_id")
        if not project_id:
            return None
        
        project = await self.db.projects.find_one({"_id": project_id})
        if not project:
            return None
        
        # 查找项目负责人或项目经理
        members = project.get("members", [])
        
        # 优先查找项目负责人（owner）
        for member in members:
            if member.get("role") == "owner":
                user = await self.db.users.find_one({"_id": member.get("user_id")})
                if user:
                    return {
                        "user_id": str(user["_id"]),
                        "role": "owner",
                        "name": user.get("name", user.get("username", ""))
                    }
        
        # 其次查找项目经理（manager）
        for member in members:
            if member.get("role") == "manager":
                user = await self.db.users.find_one({"_id": member.get("user_id")})
                if user:
                    return {
                        "user_id": str(user["_id"]),
                        "role": "manager",
                        "name": user.get("name", user.get("username", ""))
                    }
        
        return None
    
    async def _get_approvers_for_version(
        self,
        version_id: ObjectId,
        version: Dict
    ) -> List[Dict]:
        """获取多级审批人列表"""
        project_id = version.get("project_id")
        if not project_id:
            return []
        
        project = await self.db.projects.find_one({"_id": project_id})
        if not project:
            return []
        
        approvers = []
        members = project.get("members", [])
        
        # 按优先级排序：owner -> manager -> 其他有审批权限的成员
        priority_roles = ["owner", "manager"]
        
        for role in priority_roles:
            for member in members:
                if member.get("role") == role:
                    user = await self.db.users.find_one({"_id": member.get("user_id")})
                    if user:
                        approvers.append({
                            "user_id": str(user["_id"]),
                            "role": role,
                            "name": user.get("name", user.get("username", ""))
                        })
        
        return approvers

